// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   ControllerDeviceImpl.java

package backstage.runtime.ctrl;

import java.util.*;
import keel.runtime.ctrl.*;
import net.java.games.input.Component;

// Referenced classes of package backstage.runtime.ctrl:
//            ControllerDeviceConfig, ControllerConfigSet

public class ControllerDeviceImpl
    implements ControllerDevice
{
    static class ControllerRestorerImpl
        implements ControllerRestorer
    {

        public Controller restore()
        {
            ControllerDeviceManager manager = ControllerDeviceManager.getManager();
            ControllerDevice device = manager.searchControllerDevice(deviceId);
            if(device == null || !device.checkConversion(descriptor, conversion))
                return null;
            else
                return device.createController(descriptor, conversion);
        }

        String deviceId;
        ControllerDescriptor descriptor;
        ControllerDeviceConversion conversion;

        ControllerRestorerImpl(String id, ControllerDescriptor desc, ControllerDeviceConversion conv)
        {
            deviceId = id;
            descriptor = desc;
            conversion = conv;
        }
    }

    class ControllerImpl extends AbstractController
    {

        protected boolean updateImpl()
        {
            if(disposed)
            {
                return false;
            } else
            {
            	ControllerDeviceImpl.this.update();
                return true;
            }
        }

        protected boolean[] stateButton(ControllerElement button)
        {
            int code[] = (int[])conversion.getDeviceCode(button);
            boolean pressed[] = new boolean[code.length];
            for(int j = 0; j < code.length; j++)
                if(code[j] < buttonsPressed.length)
                    pressed[j] = buttonsPressed[code[j]];

            return pressed;
        }

        protected float[] stateAxis(ControllerElement axis)
        {
            int code[] = (int[])conversion.getDeviceCode(axis);
            float point[] = new float[code.length];
            for(int j = 0; j < code.length; j++)
                if(code[j] < axisValues.length)
                    point[j] = axisValues[code[j]];

            return point;
        }

        protected float[] stateHatswitch(ControllerElement hatswitch)
        {
            int code[] = (int[])conversion.getDeviceCode(hatswitch);
            float value[] = new float[code.length];
            for(int j = 0; j < code.length; j++)
                if(code[j] < hatswitchValues.length)
                    value[j] = hatswitchValues[code[j]];

            return value;
        }

        ControllerDeviceConversion getConversion()
        {
            return conversion;
        }

        void setConversion(ControllerDeviceConversion conv)
        {
            conversion = conv;
        }

        public void dispose()
        {
            disposed = true;
            deleteController(this);
        }

        public boolean equals(Object o)
        {
            if(!super.equals(o))
                return false;
            if(!(o instanceof ControllerImpl))
                return false;
            ControllerImpl ct = (ControllerImpl)o;
            return deviceId.equals(ct.getDeviceID());
        }

        String getDeviceID()
        {
            return deviceId;
        }

        public ControllerRestorer getRestorer()
        {
            return new ControllerRestorerImpl(deviceId, descriptor, conversion);
        }

        public Object getSource()
        {
            return ControllerDeviceImpl.this;
        }

        ControllerDeviceConversion conversion;
        volatile boolean disposed;

        ControllerImpl(ControllerDescriptor descriptor)
        {
            super(descriptor);
            disposed = false;
        }
    }


    public ControllerDeviceImpl(net.java.games.input.Controller pad)
    {
    	int hatswitches=0;
    	jinputpad = pad;
    	Component padcoms[] = pad.getComponents();
    	ArrayList buttonsComsList = new ArrayList();
    	ArrayList axesComsList =new ArrayList();
    	ArrayList axesNameList =new ArrayList();
    	for(int i=0;i<padcoms.length;++i)
    	{
    		if(padcoms[i].getIdentifier() instanceof Component.Identifier.Axis)
    		{
    			if(padcoms[i].getIdentifier() == Component.Identifier.Axis.POV)
    			{
    				hatswitches=1;
    			}
    		}
    		else if(padcoms[i].getIdentifier() instanceof Component.Identifier.Button)
    		{
    			buttonsComsList.add(padcoms[i]);
    		}
    	}
    	Component testCom=pad.getComponent(Component.Identifier.Axis.X);
    	if(testCom!=null)
    	{
    		axesComsList.add(testCom);
    		axesNameList.add("X axis");
    	}
    	testCom=pad.getComponent(Component.Identifier.Axis.Y);
    	if(testCom!=null)
    	{
    		axesComsList.add(testCom);
    		axesNameList.add("Y axis");
    	}
    	testCom=pad.getComponent(Component.Identifier.Axis.Z);
    	if(testCom!=null)
    	{
    		axesComsList.add(testCom);
    		axesNameList.add("Z axis");
    	}
    	testCom=pad.getComponent(Component.Identifier.Axis.RX);
    	if(testCom!=null)
    	{
    		axesComsList.add(testCom);
    		axesNameList.add("R axis");
    	}
    	testCom=pad.getComponent(Component.Identifier.Axis.RY);
    	if(testCom!=null)
    	{
    		axesComsList.add(testCom);
    		axesNameList.add("U axis");
    	}
    	testCom=pad.getComponent(Component.Identifier.Axis.RZ);
    	if(testCom!=null)
    	{
    		axesComsList.add(testCom);
    		axesNameList.add("V axis");
    	}
    	buttonComs=(Component[])buttonsComsList.toArray(new Component[0]);
    	axesComs=(Component[])axesComsList.toArray(new Component[0]);
    	///
        numButtons = buttonsComsList.size();
        numAxes = axesComsList.size();
        numHatswitches = hatswitches;
        deviceId = "gamepad_port_" + pad.getPortNumber();
        config = ControllerConfigSet.getConfigSet().getConfig(this);
        if(config == null)
        {
            config = new ControllerDeviceConfig(deviceId, pad.getName(), numButtons, numAxes, hatswitches, new int[numAxes], new int[numAxes],(String[])axesNameList.toArray(new String[0]));
            ControllerConfigSet.getConfigSet().putConfig(this, config);
        }
        buttonsPressed = new boolean[numButtons];
        axisValues = new float[numAxes];
        for(int i = 0; i < axisValues.length; i++)
            axisValues[i] = 0.0f;

        hatswitchValues = new float[hatswitches];
        controllerList = new ArrayList();
    }

    public int getNumButtons()
    {
        return numButtons;
    }

    public int getNumAxes()
    {
        return numAxes;
    }

    public int getNumHatswitches()
    {
        return numHatswitches;
    }

    public void update()
    {
        if(disabled)
        {
            return;
        } else
        {
            poll();
            return;
        }
    }

    public boolean isButtonPressed(int code)
    {
        if(code < 0 || code >= buttonsPressed.length)
            throw new IllegalArgumentException("invalid code");
        else
            return buttonsPressed[code];
    }

    public float getAxisValue(int code)
    {
        if(code < 0 || code >= axisValues.length)
            throw new IllegalArgumentException("invalid code");
        else
            return axisValues[code];
    }

    public float getHatswitchValue(int code)
    {
        if(code < 0 || code >= hatswitchValues.length)
            throw new IllegalArgumentException("invalid code");
        else
            return hatswitchValues[code];
    }

    public boolean[] getButtonsPressed()
    {
        return buttonsPressed;
    }

    public float[] getHatswitchValues()
    {
        return hatswitchValues;
    }

    public synchronized int waitForButton(long timeout)
        throws InterruptedException
    {       
    	long end= System.currentTimeMillis() + timeout;
        boolean currentDisabled= disabled;
        disabled = true;
        
        try
        {
        	
        	boolean buttonsPressedLast[]= (boolean[])getButtonsPressed().clone();
            boolean buttonsPressed[];
            int code = -1;
            
            while(code < 0)
            {
            	Thread.sleep(20L);
                if(timeout != 0L && System.currentTimeMillis() > end)
                	return -1;
                
                poll();
                buttonsPressed = getButtonsPressed();
                for(int i = 0; i < buttonsPressed.length; i++)
                {
                    if(buttonsPressedLast[i] != buttonsPressed[i])
                    {
                        code = i;
                        break;    	
                    }
                }	
            }
            
            do
            {
            	Thread.sleep(20L);
            	if(timeout != 0L && System.currentTimeMillis() > end)
                	return -1;
                
                poll();
                buttonsPressed = getButtonsPressed();	
            }while(buttonsPressed[code]);
           
            return code;	
        }
        finally
        {
        	disabled = currentDisabled;	
        }
    }

    public synchronized int waitForAxis(long timeout)
        throws InterruptedException
    {
        long end= System.currentTimeMillis() + timeout;
        boolean currentDisabled = disabled;
        disabled = true;
        
        try
        {
        	float axisValuesLast[] = (float[])getAxisValues().clone();
        	
            do
            {
            	float axisValues[];
                
                Thread.sleep(20L);
                poll();
                axisValues = getAxisValues();
                
                for(int i=0;i < axisValues.length;i++)
                {
                	if((double)Math.abs(axisValuesLast[i] - axisValues[i]) >= 0.5D)
                      return i;   	
                }
                
             }while(timeout == 0L || System.currentTimeMillis() <= end);
       
           return -1;
	
        }
        finally
        {
        	disabled = currentDisabled;	
        }
    }

    public synchronized int waitForHatswitch(long timeout)
        throws InterruptedException
    {
        long end = System.currentTimeMillis() + timeout;
        boolean currentDisabled = disabled;
        disabled = true;
        
        try
        {
        	float hatswitchValuesLast[] = (float[])getHatswitchValues().clone();
        	
            do
            {
                    float hatswitchValues[];
                    
                    Thread.sleep(20L);
                    poll();
                    hatswitchValues = getHatswitchValues();
                    
                    for(int i=0;i < axisValues.length;i++)
                    {
                    	if(hatswitchValuesLast[i] != hatswitchValues[i])
                    		return i;	
                    }
                            	
            }while(timeout == 0L || System.currentTimeMillis() <= end);

            return -1;
        }
        finally
        {
        	disabled = currentDisabled;	
        }
    }

    private float[] getAxisValues()
    {
        return axisValues;
    }

    public void poll()
    {
    	jinputpad.poll();
    	for(int i=0;i<axesComs.length;++i)
    		axisValues[i]=axesComs[i].getPollData();
    	for(int i=0;i<buttonComs.length;++i)
    		buttonsPressed[i]=buttonComs[i].getPollData()==1.0f;
    	if(numHatswitches==1)
    	{
    		float t=jinputpad.getComponent(Component.Identifier.Axis.POV).getPollData();
    		if(t==0.0f)
    			hatswitchValues[0]=-1.0f;
    		else
    		{
    			t=1.0f-t;if(t>=0.0f && t<0.25f)t+=1.0f;
    			hatswitchValues[0]=(float) ((t-0.25f)*2.0f*Math.PI);
    		}
    	}
    }

    public String getDeviceID()
    {
        return deviceId;
    }

    public ControllerDeviceConfig getConfig()
    {
        return config;
    }

    public synchronized void setConfig(ControllerDeviceConfig cdc)
    {
        if(!deviceId.equals(cdc.getDeviceID()))
            throw new IllegalArgumentException("device ID is not match");
        config = cdc;
        ControllerImpl ct;
        for(Iterator it = controllerList.iterator(); it.hasNext(); ct.setConversion(cdc.getConversion(ct.getDescriptor())))
            ct = (ControllerImpl)it.next();

    }

    public synchronized void dispose()
    {
        disabled = true;
    }

    public Controller createController(ControllerDescriptor descriptor)
    {
        ControllerDeviceConversion conversion = config.getConversion(descriptor);
        return createController(descriptor, conversion);
    }

    public synchronized Controller createController(ControllerDescriptor descriptor, ControllerDeviceConversion conversion)
    {
        if(descriptor == null)
        {
            throw new NullPointerException("descriptor is null");
        } else
        {
            ControllerImpl ct = new ControllerImpl(descriptor);
            controllerList.add(ct);
            setConversion(ct, conversion);
            return ct;
        }
    }

    public synchronized Controller[] getControllers()
    {
        return (Controller[])controllerList.toArray(new Controller[0]);
    }

    public synchronized void deleteController(Controller ct)
    {
        controllerList.remove(ct);
    }

    public synchronized void setConversion(Controller ct, ControllerDeviceConversion conv)
    {
        if(!controllerList.contains(ct))
            throw new IllegalArgumentException("couldn't find controller : " + ct);
        if(conv == null)
            throw new NullPointerException("conv is null");
        ControllerDeviceConversion conversion = (ControllerDeviceConversion)conv.clone();
        if(!checkConversion(ct.getDescriptor(), conversion))
        {
            throw new IllegalArgumentException("illegal conversion");
        } else
        {
            ((ControllerImpl)ct).setConversion(conversion);
            config.setConversion(ct.getDescriptor(), conversion);
            return;
        }
    }

    public synchronized ControllerDeviceConversion getConversion(Controller ct)
    {
        if(!controllerList.contains(ct))
        {
            throw new IllegalArgumentException("couldn't find controller : " + ct);
        } else
        {
            ControllerDeviceConversion conv = ((ControllerImpl)ct).getConversion();
            return conv;
        }
    }

    public synchronized void processControllerEvents()
    {
    }

    public boolean isSufficient(ControllerDescriptor descriptor)
    {
        int buttonCount = 0;
        for(Iterator i = descriptor.getButtons().iterator(); i.hasNext();)
            buttonCount += ((ControllerElement)i.next()).getNumElements();

        if(numButtons < buttonCount)
            return false;
        int axisCount = 0;
        for(Iterator i = descriptor.getAxes().iterator(); i.hasNext();)
            axisCount += ((ControllerElement)i.next()).getNumElements();

        if(numAxes < axisCount)
            return false;
        int hatswitchCount = 0;
        for(Iterator i = descriptor.getHatswitches().iterator(); i.hasNext();)
            hatswitchCount += ((ControllerElement)i.next()).getNumElements();

        return numHatswitches >= hatswitchCount;
    }

    public boolean checkConversion(ControllerDescriptor descriptor, ControllerDeviceConversion conversion)
    {
        for(Iterator i = descriptor.getButtons().iterator(); i.hasNext();)
        {
            ControllerElement button = (ControllerElement)i.next();
            Object codeObj = conversion.getDeviceCode(button);
            if(codeObj == null || !(codeObj instanceof int[]))
                return false;
            int code[] = (int[])codeObj;
            for(int j = 0; j < code.length; j++)
                if(code[j] < 0)
                    return false;

        }

        for(Iterator i = descriptor.getAxes().iterator(); i.hasNext();)
        {
            ControllerElement axis = (ControllerElement)i.next();
            Object codeObj = conversion.getDeviceCode(axis);
            if(codeObj == null || !(codeObj instanceof int[]))
                return false;
            int code[] = (int[])codeObj;
            for(int j = 0; j < code.length; j++)
                if(code[j] < 0)
                    return false;

        }

        for(Iterator i = descriptor.getHatswitches().iterator(); i.hasNext();)
        {
            ControllerElement hatswith = (ControllerElement)i.next();
            Object codeObj = conversion.getDeviceCode(hatswith);
            if(codeObj == null || !(codeObj instanceof int[]))
                return false;
            int code[] = (int[])codeObj;
            for(int j = 0; j < code.length; j++)
                if(code[j] < 0)
                    return false;

        }

        return true;
    }

    int numButtons;
    int numAxes;
    int numHatswitches;
    String deviceId;
    boolean buttonsPressed[];
    float axisValues[];
    float hatswitchValues[];
    ControllerDeviceConfig config;
    //long nativeContext;
    volatile boolean disabled;
    List controllerList;
    
    net.java.games.input.Controller jinputpad;
    Component axesComs[];
    Component buttonComs[];
}
